#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Input;
#endregion

namespace TurbaconPhone
{
    class MenuState : State
    {
        InputState input = new InputState();
        SpriteFont font;
        List<MenuEntry> menuEntries = new List<MenuEntry>();
        const int menuEntryPadding = 10;
        int selectedEntry = 0;
        Texture2D bg = TurBacon.Content.GetTexture("firebowl_menu");
        public MenuState()
        {
            font = TurBacon.Content.GetFont("menu");
           
        }

        float transitionPosition = 1;
        public float TransitionPosition
        {
            get { return transitionPosition; }
            protected set { transitionPosition = value; }
        }

        /// <summary>
        /// Controls whether the animation is updated when calling <see cref="Update"/>.
        /// </summary>
        public bool IsActive { get; set; }

        /// <summary>
        /// Allows the screen to create the hit bounds for a particular menu entry.
        /// </summary>
        protected virtual Rectangle GetMenuEntryHitBounds(MenuEntry entry)
        {
            // the hit bounds are the entire width of the screen, and the height of the entry
            // with some additional padding above and below.
            return new Rectangle(
                0,
                (int)entry.Position.Y - menuEntryPadding,
                TurBacon.Game.GraphicsDevice.Viewport.Width,
                entry.GetHeight() + (menuEntryPadding * 2));
        }

        /// <summary>
        /// Gets the index of the player who is currently controlling this screen,
        /// or null if it is accepting input from any player. This is used to lock
        /// the game to a specific player profile. The main menu responds to input
        /// from any connected gamepad, but whichever player makes a selection from
        /// this menu is given control over all subsequent screens, so other gamepads
        /// are inactive until the controlling player returns to the main menu.
        /// </summary>
        public PlayerIndex? ControllingPlayer
        {
            get { return controllingPlayer; }
            internal set { controllingPlayer = value; }
        }

        PlayerIndex? controllingPlayer;


        /// <summary>
        /// Handler for when the user has chosen a menu entry.
        /// </summary>
        protected virtual void OnSelectEntry(int entryIndex, PlayerIndex playerIndex)
        {
            menuEntries[entryIndex].OnSelectEntry(playerIndex);
        }


        
        /// <summary>
        /// Handler for when the user has cancelled the menu.
        /// </summary>
        protected virtual void OnCancel(PlayerIndex playerIndex)
        {
            
        }
        /// <summary>
        /// Helper overload makes it easy to use OnCancel as a MenuEntry event handler.
        /// </summary>
        protected void OnCancel(object sender, PlayerIndexEventArgs e)
        {
            OnCancel(e.PlayerIndex);
        }
        /// <summary>
        /// Allows the screen the chance to position the menu entries. By default
        /// all menu entries are lined up in a vertical list, centered on the screen.
        /// </summary>
        protected virtual void UpdateMenuEntryLocations()
        {
            // Make the menu slide into place during transitions, using a
            // power curve to make things look more interesting (this makes
            // the movement slow down as it nears the end).
            float transitionOffset = (float)Math.Pow(TransitionPosition, 2);

            // start at Y = 175; each X value is generated per entry
            Vector2 position = new Vector2(0f, 175f);

            // update each menu entry's location in turn
            for (int i = 0; i < menuEntries.Count; i++)
            {
                MenuEntry menuEntry = menuEntries[i];

                // each entry is to be centered horizontally
                position.X = TurBacon.Game.GraphicsDevice.Viewport.Width / 2 - menuEntry.GetWidth() / 2;
//                position.X = ScreenManager.GraphicsDevice.Viewport.Width / 2 - menuEntry.GetWidth(this) / 2;

                //if (ScreenState == ScreenState.TransitionOn)
                //    position.X -= transitionOffset * 256;
                //else
                //    position.X += transitionOffset * 512;

                // set the entry's position
                menuEntry.Position = position;

                // move down for the next entry the size of this entry plus our padding
                position.Y += menuEntry.GetHeight() + (menuEntryPadding * 2);
            }
        }
        InputState inputState = new InputState();
        public override void EnterState()
        {
            EnabledGestures = GestureType.Tap | GestureType.FreeDrag;
            base.EnterState();
            MenuEntry gameEntry = new MenuEntry("Start");
            MenuEntry optionsEntry = new MenuEntry("Help");
            MenuEntry aboutEntry = new MenuEntry("About");
            
            menuEntries.Add(gameEntry);
            menuEntries.Add(optionsEntry);
            menuEntries.Add(aboutEntry);

            gameEntry.Selected += GameEntrySelected;
            optionsEntry.Selected += OptionsEntrySelected;
            aboutEntry.Selected += AboutEntrySelected;
        }

        public override void Draw(SpriteBatch spriteBatch)
        {
            TurBacon.Batch.Begin();
            TurBacon.Batch.Draw(bg, new Rectangle(0, 0, TurBacon.Game.GraphicsDevice.Viewport.Width, TurBacon.Game.GraphicsDevice.Viewport.Height), Color.White);
            for (int i = 0; i < menuEntries.Count; i++)
            {
                MenuEntry menuEntry = menuEntries[i];

                bool isSelected = IsActive && (i == selectedEntry);

                menuEntry.Draw(isSelected);
            }

            TurBacon.Batch.End();
        }
        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
            UpdateMenuEntryLocations();

            TurBacon.Batch.Begin();
            for (int i = 0; i < menuEntries.Count; i++)
            {
                MenuEntry menuEntry = menuEntries[i];

                bool isSelected = IsActive && (i == selectedEntry);

                menuEntry.Update(isSelected, gameTime);
            }
            
            //spriteBatch.DrawString(font, menuTitle, titlePosition, titleColor, 0,
            //                                  titleOrigin, titleScale, SpriteEffects.None, 0);
            
            TurBacon.Batch.End();
        }
        /// <summary>
        /// Event handler for when the Play Game menu entry is selected.
        /// </summary>
        void GameEntrySelected(object sender, PlayerIndexEventArgs e)
        {
            TurBacon.StateManager.Pop();
            TurBacon.StateManager.Push(new GameplayState());
        }

        /// <summary>
        /// Event handler for when the Play Game menu entry is selected.
        /// </summary>
        void OptionsEntrySelected(object sender, PlayerIndexEventArgs e)
        {
            TurBacon.StateManager.Pop();
            TurBacon.StateManager.Push(new OptionsState());
        }

        /// <summary>
        /// Event handler for when the Play Game menu entry is selected.
        /// </summary>
        void AboutEntrySelected(object sender, PlayerIndexEventArgs e)
        {
            TurBacon.StateManager.Pop();
            TurBacon.StateManager.Push(new AboutState());
        }
        public override void HandleInput()
        {
            base.HandleInput();
            HandleInput(inputState);
        }

        public override void HandleTap(GestureSample gesture)
        {
            base.HandleTap(gesture);
            // convert the position to a Point that we can test against a Rectangle
                    Point tapLocation = new Point((int)gesture.Position.X, (int)gesture.Position.Y);

                    // iterate the entries to see if any were tapped
                    for (int i = 0; i < menuEntries.Count; i++)
                    {
                        MenuEntry menuEntry = menuEntries[i];

                        if (GetMenuEntryHitBounds(menuEntry).Contains(tapLocation))
                        {
                            // select the entry. since gestures are only available on Windows Phone,
                            // we can safely pass PlayerIndex.One to all entries since there is only
                            // one player on Windows Phone.
                            OnSelectEntry(i, PlayerIndex.One);
                        }
                    }
                
        }
        /// <summary>
        /// Responds to user input, changing the selected entry and accepting
        /// or cancelling the menu.
        /// </summary>
        public void HandleInput(InputState input)
        {
            // we cancel the current menu screen if the user presses the back button
            PlayerIndex player;
            if (input.IsNewButtonPress(Buttons.Back, ControllingPlayer, out player))
            {
                OnCancel(player);
            }

            // look for any taps that occurred and select any entries that were tapped
            foreach (GestureSample gesture in input.Gestures)
            {
                if (gesture.GestureType == GestureType.Tap)
                {
                    // convert the position to a Point that we can test against a Rectangle
                    Point tapLocation = new Point((int)gesture.Position.X, (int)gesture.Position.Y);

                    // iterate the entries to see if any were tapped
                    for (int i = 0; i < menuEntries.Count; i++)
                    {
                        MenuEntry menuEntry = menuEntries[i];

                        if (GetMenuEntryHitBounds(menuEntry).Contains(tapLocation))
                        {
                            // select the entry. since gestures are only available on Windows Phone,
                            // we can safely pass PlayerIndex.One to all entries since there is only
                            // one player on Windows Phone.
                            OnSelectEntry(i, PlayerIndex.One);
                        }
                    }
                }
            }
        }
    }
}
